package com.guang.springbootselfmvc.utils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class JsonUtil {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final Map<Class<?>, ObjectReader> readerMap = new ConcurrentHashMap();
    private static final Map<Class<?>, ObjectWriter> writerMap = new ConcurrentHashMap();
    private static final JsonFactory jsonFactory = new JsonFactory();
    private static final Map<Class<?>, JavaType> collectionElementMap = new ConcurrentHashMap();

    public JsonUtil() {
    }

    private static JavaType getJavaType(Class<?> targetClass) {
        Object javaType;
        if ((javaType = (JavaType)collectionElementMap.get(targetClass)) == null) {
            synchronized(targetClass) {
                if ((javaType = (JavaType)collectionElementMap.get(targetClass)) == null) {
                    javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, targetClass);
                    collectionElementMap.put(targetClass, (JavaType) javaType);
                }
            }
        }
        return (JavaType)javaType;
    }

    public static <T> List<T> parseJsonStringToListObject(String jsonString, Class<T> targetClass) throws Exception {
        ObjectReader reader = getObjectReader(List.class);
        JavaType javaType = getJavaType(targetClass);
        return (List)reader.readValue(jsonFactory.createParser(jsonString), javaType);
    }

    public static <T> List parseObjectListType(List<?> objectList, Class<T> targetClass) throws Exception {
        List<T> result = new ArrayList(objectList.size());
        Iterator var3 = objectList.iterator();

        while(var3.hasNext()) {
            Object object = var3.next();
            result.add(parseObjectToObject(object, targetClass));
        }

        return result;
    }

    public static <T> T parseObjectToObject(Object object, Class<T> targetClass) throws Exception {
        return parseJsonStringToObject(parseObjectToJsonString(object), targetClass);
    }

    public static <T> T parseJsonStringToObject(String jsonString, Class<T> targetClass) throws Exception {
        ObjectReader reader = getObjectReader(targetClass);
        return reader.readValue(jsonString);
    }

    public static String parseObjectToJsonString(Object object) throws Exception {
        ObjectWriter writer = getObjectWriter(object.getClass());
        return writer.writeValueAsString(object);
    }

    private static ObjectReader getObjectReader(Class<?> targetClass) {
        ObjectReader reader;
        if ((reader = (ObjectReader)readerMap.get(targetClass)) == null) {
            synchronized(targetClass) {
                if ((reader = (ObjectReader)readerMap.get(targetClass)) == null) {
                    reader = objectMapper.readerFor(targetClass);
                    readerMap.put(targetClass, reader);
                }
            }
        }

        return reader;
    }

    private static ObjectWriter getObjectWriter(Class<?> targetClass) {
        ObjectWriter writer;
        if ((writer = (ObjectWriter)writerMap.get(targetClass)) == null) {
            synchronized(targetClass) {
                if ((writer = (ObjectWriter)writerMap.get(targetClass)) == null) {
                    writer = objectMapper.writerFor(targetClass);
                    writerMap.put(targetClass, writer);
                }
            }
        }

        return writer;
    }

    /**
     * 设置序列化操作
     */
    static {
        /**
         *
         * https://blog.csdn.net/fzy629442466/article/details/104752490
         * 将该标记放在属性上，如果该属性为NULL则不参与序列化
         * 如果放在类上边,那对这个类的全部属性起作用
         * 值参考：
         * ① Include.Include.ALWAYS 默认
         * ② Include.NON_DEFAULT 属性为默认值不序列化
         * ③ Include.NON_EMPTY 属性为 空（“”） 或者为 NULL 都不序列化
         * ④ Include.NON_NULL 属性为NULL 不序列化
         */
        objectMapper.setSerializationInclusion(Include.NON_NULL);
        // 序列化：序列化BigDecimal时不使用科学计数法输出
        objectMapper.configure(Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
        /**
         * springboot中日期格式化问题
         * 参考链接：https://blog.csdn.net/weixin_44299027/article/details/104516280
         * spring:
         *   jackson:
         *     date-format: yyyy-MM-dd HH:mm:ss
         *     time-zone: GMT+8
         *     serialization:
         *       write-dates-as-timestamps: false
         */
        // 写入的时间。springmvc中默认的是yyyy-MM-dd'T'HH:mm:ss.SSS，如果是yyyy-MM-dd HH:mm:ss类型的，那么需要关闭掉
        // 这里的配置文件是取消这里的时间转换
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 写入的
        objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
    }
}